import numpy as np
from scipy.optimize import minimize

# 定义年收益率期望值（股票）
R_stock = np.array([0.28, 0.20, 0.18, 0.10])

# 定义年收益率的协方差矩阵（股票）
cov_matrix_stock = np.array([[0.400, 0.055, 0.015, 0.013],
                              [0.055, 0.350, 0.016, 0.057],
                              [0.015, 0.016, 0.028, 0.078],
                              [0.013, 0.057, 0.078, 0.210]])

# 无风险投资方式的年收益率
R_rf = 0.06

# 定义风险厌恶系数
risk_aversion_coefficient = 0.5  # 调整这个系数以平衡收益和风险

# 定义二次规划目标函数
def objective(w):
    # 计算投资组合的年收益率
    portfolio_return = np.dot(R_stock, w[:-1]) + w[-1] * R_rf  # 加入无风险收益
    # 计算投资组合的方差
    portfolio_variance = np.dot(w[:-1], np.dot(cov_matrix_stock, w[:-1]))
    # 计算投资组合的效用（收益 - 风险）
    utility = portfolio_return - risk_aversion_coefficient * portfolio_variance
    return -utility  # 由于是最大化效用，因此取负号

# 定义约束条件: 投资比例与无风险投资比例之和为1
def constraint(w):
    return np.sum(w[:-1]) + w[-1] - 1

# 定义优化问题
initial_guess = np.ones(5) / 5  # 初始猜测，均匀分配
constraints = ({'type': 'eq', 'fun': constraint})
bounds = tuple((0, None) for _ in range(5))  # 投资比例非负

# 求解二次规划问题
result = minimize(objective, initial_guess, method='SLSQP', bounds=bounds, constraints=constraints)

# 计算最优投资组合的方差（风险）
optimal_portfolio_variance = np.dot(result.x[:-1], np.dot(cov_matrix_stock, result.x[:-1]))

# 输出结果
print("最优投资比例（股票）为：", result.x[:-1])
print("无风险投资比例为：", result.x[-1])
print("最优投资组合的年收益率为：", np.dot(R_stock, result.x[:-1])+ result.x[-1] * R_rf)
print("最优投资组合的风险（方差）为：", optimal_portfolio_variance)
